package org.rambadger.command.model;

import org.axonframework.eventhandling.annotation.EventHandler;
import org.axonframework.eventsourcing.annotation.AbstractAnnotatedEntity;
import org.rambadger.command.event.AssignmentAddedToTrack;
import org.rambadger.command.event.AssignmentMovedWithinTrack;
import org.rambadger.command.event.AssignmentRemovedFromTrack;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * Entity type representing a track, which contains an ordered sequence of assignments that have to be completed in order.
 *
 * @see PlatformAggregate
 * @see AssignmentEntity
 */
public class TrackEntity extends AbstractAnnotatedEntity implements Serializable {
    private static final long serialVersionUID = -2519231143709107098L;

    private final String trackId;
    private String trackName;
    private String description;
    private List<String> assignments;

    /**
     * Instantiates a new Track entity with no {@link AssignmentEntity assignments}.
     *
     * @param trackId the track id
     * @param trackName the track display name name
     * @param description the description
     */
    public TrackEntity(String trackId, String trackName, String description) {
        this.trackId = trackId;
        this.trackName = trackName;
        this.description = description;
        this.assignments = new LinkedList<>();
    }

    @EventHandler void on(AssignmentAddedToTrack event) {
        if (event.getTrackId().equals(trackId)) {
            assignments.add(event.getIndex(), event.getAssignmentId());
        }
    }

    @EventHandler void on(AssignmentMovedWithinTrack event) {
        if (event.getTrackId().equals(trackId))  {
            assignments.remove(event.getAssignmentId());
            assignments.add(event.getIndex(), event.getAssignmentId());
        }
    }

    @EventHandler void on(AssignmentRemovedFromTrack event) {
        if (event.getTrackId().equals(trackId)) {
            assignments.remove(event.getAssignmentId());
        }
    }

    /**
     * Gets the track id.
     * <p>
     *     Used for databases and URLs.
     * </p>
     *
     * @return the track id
     */
    public String getTrackId() {
        return trackId;
    }

    /**
     * Gets the display name of the track.
     *
     * @return the track name
     */
    public String getTrackName() {
        return trackName;
    }

    /**
     * Gets description.
     *
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * Gets the ordered list of assignment ids belonging to the track.
     *
     * @return the assignments ids
     */
    public List<String> getAssignments() {
        return assignments;
    }

    /**
     * Determines if the platform contains an assignment with the specified id.
     *
     * @param assignmentId the assignment id
     * @return whether the track contains the assignment
     */
    public boolean hasAssignment(String assignmentId) {
        return assignments.contains(assignmentId);
    }
}
